package comunicacao.moderador;

import java.io.File;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import comunicacao.faces.IFModerador;
import comunicacao.faces.IFServidor;

public class Moderador implements IFModerador {

	Registry registry;
	IFServidor stubServidor;
	
	private ArrayList<Arquivo> listaArquivo = new ArrayList<Arquivo>();
	private ArrayList<Clientes> listaClientes = new ArrayList<Clientes>();
	Arquivo arq = new Arquivo();
	Clientes cliente = new Clientes();
	
	/**
	 * Construtor responsavel por iniciar os metodos de conexao cliente/moderador
	 * e moderador/servidor
	 *
	 */
	public Moderador() {
		iniciaServidor();
		iniciaCliente();
	}

	/**
	 * Exporta objeto remoto para acesso do cliente
	 *
	 */
	public void iniciaServidor() {
		try {
			IFModerador stubCliente = (IFModerador) UnicastRemoteObject.exportObject(this, 0);
			Registry registry = LocateRegistry.createRegistry(1001);
			registry.bind("Moderador", stubCliente);

			System.out.println("Moderador iniciado...");
		} catch (RemoteException Re) {
			System.out.println(Re.getMessage());
		} catch (AlreadyBoundException ABe) {
			System.out.println(ABe.getMessage());
		}catch (Throwable t){
			t.printStackTrace();
		}
	}
	
	/**
	 * Inicia conexao com o servidor.
	 *
	 */
	private void iniciaCliente() {
		try {
			registry = LocateRegistry.getRegistry("localhost", 1000);
			stubServidor = (IFServidor) registry.lookup("Servidor");
			System.out.println("Conexao realizada com sucesso..");
		} catch (RemoteException Re) {
			Re.printStackTrace();
		} catch (NotBoundException NBe) {
			NBe.printStackTrace();
		}
	}
	
	/**
	 * Faz requisição de download ao servidor, verifica se arquivo esta sendo utilizado e/ou existe
	 * e encaminha ao cliente
	 * @param arquivo
	 */
	public byte[] getDownload(String arquivo, int porta){
		if(!ArquivoEmUso(arquivo)){
			try{
				byte[] encaminharArquivo = stubServidor.getDownload(arquivo);
				addArquivoExclMutua(arquivo, porta);
				return encaminharArquivo;
			}catch (RemoteException e) {
				e.printStackTrace();
				System.out.println("O arquivo nao foi encontrado.");
				return null;
			}
		}else{
			System.out.println("O arquivo esta em uso.");
			return null;
		}
	}
	
	/**
	 * Faz requisição da listagem ao servidor e encaminha ao cliente
	 */
	public File[] listarArquivos(){
		System.out.println("Vou mandar arquivos de volta.");
		try{
			File[] encaminharLista = stubServidor.listarArquivos();
			return encaminharLista;
		}catch (RemoteException e) {
			return null;
		}
	}
	
	/**
	 * Adiciona arquivo na lista de exclusao mutua e seta como se arquivo estivesse sendo utilizado
	 * @param arquivo
	 */
	private void addArquivoExclMutua(String arquivo, int porta) {
		arq.setArquivo(arquivo);
		arq.setEstaEmUso(true);
		arq.setPorta(porta);
		if (!verificaCliente(porta)){
			cliente.setPorta(porta);
			listaClientes.add(cliente);
		}
		listaArquivo.add(arq);
	}

	/**
	 * Verifica se arquivo esta sendo utilizado
	 * @param arquivo
	 * @return
	 */
	private boolean ArquivoEmUso(String arquivo) {
		for (Arquivo arq : listaArquivo) {
			if (arq.getArquivo().equals(arquivo)) {
				if (arq.isEstaEmUso()) {
					return true;
				} else {
					return false;
				}
			}
		}
		return false;
	}

	/**
	 * Adiciona o cliente com seu porta
	 */

	public boolean verificaCliente(int porta) {
		for (Clientes cliente : listaClientes) {
			if ( cliente.getPorta() == porta) {
				return true;
			}else{
				return false;
			}
		}
		return false;
	}

	/**
	 * Altera status de arquivo na lista de exclusão mutua
	 */
	public void pararExececucaoArquivo(String arquivo, int porta) {
		for (Arquivo arq : listaArquivo) {
			if (arq.getArquivo().equals(arquivo)) {
				if (arq.getPorta() == porta){
					arq.setEstaEmUso(false);
					listaArquivo.remove(arquivo);
				}else{
					System.out.println("Arquivo em uso pelo Cliente na porta " + arq.getPorta());
				}
			}
		}
	}
	
	public static void main(String args[]) {
		new Moderador();
	}

	
}
